home *** CD-ROM | disk | FTP | other *** search
- (*===========================================================================*)
- (* Procedure to send/receive things to a telephone modem *)
- (* *)
- (* Copyright 1988, 1989, 1990 by H. Roy Engehausen. All rights reserved. *)
- (* *)
- (*===========================================================================*)
-
- (*===========================================================================*)
- (* Main procedure *)
- (* *)
- (* Parm = 0 -- Data *)
- (* 1 -- Data *)
- (* 2 -- General Poll *)
- (* 3 -- Data Poll *)
- (* 4 -- Link Status Poll *)
- (* 5 -- Data ack poll *)
- (*===========================================================================*)
-
- {$UNDEF DEBUG_UPMODEM}
-
- PROCEDURE send_recv_modem(tnc_cmd_data : BYTE);
-
- VAR
- b : BOOLEAN;
- i : BYTE;
- regs : REGISTERS;
- s : CHAR;
- set_dx : BYTE;
-
- (*=========================================================================*)
- (* Short wait *)
- (*=========================================================================*)
-
- PROCEDURE short_wait;
-
- VAR
- i : BYTE;
-
- BEGIN;
-
- IF active_tcb^.tcb_type = th_main THEN
- DELAY(700)
- ELSE
- task_wait(1, FALSE);
-
- END;
-
-
- (*=========================================================================*)
- (* Set null answer procedure *)
- (*=========================================================================*)
-
- PROCEDURE set_null;
- BEGIN;
-
- active_tcb^.tnc_null := TRUE;
-
- active_tcb^.tnc_type := t_to_h_ok;
-
- active_tcb^.tnc_data.str_data := '';
- active_tcb^.tnc_data.long_length := 0;
-
- END;
-
- (*=========================================================================*)
- (* Queue received data onto thread control block *)
- (*=========================================================================*)
-
- PROCEDURE queue_received_data;
-
- VAR
- data_save : str_mixed;
- i : WORD;
- add_tcb : tcb_ptr;
-
- BEGIN;
-
- WITH active_tcb^.tnc_tth^ DO
- BEGIN;
-
- (*-----------------------------------------------------------------*)
- (* If we have no data, then we leave *)
- (*-----------------------------------------------------------------*)
-
- i := data67_count;
- IF i = 0 THEN
- EXIT;
-
- (*-----------------------------------------------------------------*)
- (* Save buffer. *)
- (*-----------------------------------------------------------------*)
-
- IF tnc_cmd_data < 2 THEN
- data_save := active_tcb^.tnc_data;
-
- (*-----------------------------------------------------------------*)
- (* Move data from buffer to tnc data area *)
- (*-----------------------------------------------------------------*)
-
- active_tcb^.tnc_data.long_length := i;
- MOVE(data67, active_tcb^.tnc_data.long_data, i);
- IF i > 255 THEN
- i := 255;
- active_tcb^.tnc_data.str_data[0] := CHR(i);
-
- (*-----------------------------------------------------------------*)
- (* Clear the buffer *)
- (*-----------------------------------------------------------------*)
-
- data67_count := 0;
-
- END;
-
- (*---------------------------------------------------------------------*)
- (* Add the data to the queue *)
- (*---------------------------------------------------------------------*)
-
- active_tcb^.tnc_type := t_to_h_conn;
-
- i := 1;
- WHILE (i <= active_port^.max_chan)
- AND (active_port^.connected^[i] = NIL) DO
- INC(i);
-
- IF i <= active_port^.max_chan THEN
- add_tcb := active_port^.connected^[i]
- ELSE
- add_tcb := active_tcb;
-
- add_tnc_queue(add_tcb, add_tcb^.channel);
-
- {$IFDEF DEBUG}
- WRITELN('ADDQ=', active_tcb^.tnc_data.long_length, '=',
- active_tcb^.tnc_data.str_data);
- WRITELN('TO=',add_tcb^.port_chan_s, '-', add_tcb^.channel);
- DELAY(700);
- {$ENDIF}
-
- (*---------------------------------------------------------------------*)
- (* Restore buffer *)
- (*---------------------------------------------------------------------*)
-
- IF tnc_cmd_data < 2 THEN
- active_tcb^.tnc_data := data_save;
-
- END;
-
- (*=========================================================================*)
- (* Get data from telephone modem and put in buffer. Queue as needed *)
- (*=========================================================================*)
-
- PROCEDURE receive_telephone_modem;
-
- VAR
- b_cnt : WORD;
- first_time : BOOLEAN;
- master_thread : BOOLEAN;
- pause_expire : LONGINT;
-
- CONST
- buffer_size = 254;
- pause_to = 8;
- send_buffer_cnt = 100;
-
- LABEL
- start_buffer_over;
-
- BEGIN;
-
- master_thread := active_tcb^.tcb_type = th_main;
-
- (*---------------------------------------------------------------------*)
- (* Grab the locks *)
- (*---------------------------------------------------------------------*)
-
- get_port_semaphore;
- task_switch;
-
- WITH active_tcb^.tnc_tth^ DO
- BEGIN;
-
- (*-----------------------------------------------------------------*)
- (* Initialize things *)
- (*-----------------------------------------------------------------*)
-
- b_cnt := data67_count;
-
- start_buffer_over:
-
- regs.DI := OFS(data67[b_cnt + 1]);
- regs.ES := SEG(data67);
- regs.DX := set_dx;
-
- (*-----------------------------------------------------------------*)
- (* Force the timer to initialize *)
- (*-----------------------------------------------------------------*)
-
- regs.CX := 1;
- first_time := TRUE;
-
- (*-----------------------------------------------------------------*)
- (* Loop until we see a pause in incoming data *)
- (*-----------------------------------------------------------------*)
-
- REPEAT;
-
- (*---------------------------------------------------------------*)
- (* Calculate the current time *)
- (*---------------------------------------------------------------*)
-
- IF master_thread THEN
- calc_up_time
- ELSE
- task_switch;
-
- (*---------------------------------------------------------------*)
- (* If we got data the last time around, calculate new timeout *)
- (*---------------------------------------------------------------*)
-
- IF (regs.CX <> 0) OR first_time THEN
- pause_expire := up_time + pause_to;
-
- first_time := regs.CX <> 0;
-
- {$IFDEF DEBUG_UPMODEM}
- WRITELN(regs.CX, ' -- ', pause_time, ' -- ', up_time);
- {$ENDIF}
-
- (*---------------------------------------------------------------*)
- (* Get data *)
- (*---------------------------------------------------------------*)
-
- regs.AX := $0B00;
- regs.CX := buffer_size - b_cnt;
-
- signal_place^ := $0200 + LO(signal_place^);
-
- INTR(tnc_interrupt, regs);
-
- signal_place^ := $F800 + LO(signal_place^);
-
- (*---------------------------------------------------------------*)
- (* Bump counter *)
- (*---------------------------------------------------------------*)
-
- INC(b_cnt, regs.CX);
-
- (*---------------------------------------------------------------*)
- (* If buffer overflows then queue it and start over *)
- (*---------------------------------------------------------------*)
-
- IF b_cnt >= send_buffer_cnt THEN
- BEGIN;
- data67_count := b_cnt;
- queue_received_data;
- free_semaphore(semaphore_interrupts);
- get_semaphore(semaphore_interrupts, sem_shared, FALSE);
- b_cnt := 0;
- GOTO start_buffer_over;
- END;
-
- (*---------------------------------------------------------------*)
- (* Loop around until timeout *)
- (*---------------------------------------------------------------*)
-
- UNTIL (pause_expire < up_time) AND (regs.CX = 0);
-
- (*-----------------------------------------------------------------*)
- (* Set the result so far and leave *)
- (*-----------------------------------------------------------------*)
-
- data67_count := b_cnt;
-
- END;
-
- (*---------------------------------------------------------------------*)
- (* Drop the locks *)
- (*---------------------------------------------------------------------*)
-
- free_port_semaphore;
- task_switch;
-
- END;
-
- (*=========================================================================*)
- (* Send data to telephone modem *)
- (*=========================================================================*)
-
- {$UNDEF TRACE_ME}
-
- PROCEDURE send_telephone_modem;
-
-
- TYPE
- x = ARRAY[1..10] OF CHAR;
-
- VAR
- i : BYTE;
-
- {$IFDEF TRACE_ME}
- p : ^x;
- {$ENDIF}
-
- BEGIN;
-
-
- {$IFDEF TRACE_ME}
- trace_data('MW', active_tcb^.tnc_data.long_length, NIL,
- active_tcb^.tnc_data.str_data);
- {$ENDIF}
-
- (*---------------------------------------------------------------------*)
- (* Wait for buffer empty before sending *)
- (*---------------------------------------------------------------------*)
-
- REPEAT
-
- task_switch;
-
- regs.AX := $0300;
- regs.DX := set_dx;
- INTR(tnc_interrupt, regs);
-
- UNTIL (regs.AH AND lsr_8250_thre) <> 0;
-
- (*---------------------------------------------------------------------*)
- (* Send the data directly from the thread's buffer *)
- (*---------------------------------------------------------------------*)
-
- regs.CX := active_tcb^.tnc_data.long_length;
- regs.DI := OFS(active_tcb^.tnc_data.long_data);
- regs.ES := SEG(active_tcb^.tnc_data.long_data);
-
- REPEAT
-
- regs.AX := $0A00;
- regs.DX := set_dx;
-
- (*-------------------------------------------------------------------*)
- (* Grab the locks *)
- (*-------------------------------------------------------------------*)
-
- get_port_semaphore;
- task_switch;
-
- signal_place^ := $0200 + LO(signal_place^);
-
- INTR(tnc_interrupt, regs);
-
- signal_place^ := $F800 + LO(signal_place^);
-
- (*-------------------------------------------------------------------*)
- (* Drop the locks *)
- (*-------------------------------------------------------------------*)
-
- free_port_semaphore;
- task_switch;
-
- IF regs.CX <> 0 THEN
- BEGIN;
- FOR i := 1 TO 20 DO
- task_switch;
-
- {$IFDEF TRACE_ME}
- WRITE('Non-zero CX = ', regs.CX);
- p := PTR(regs.ES, regs.DI);
- FOR i := 1 TO 10 DO
- WRITE(p^[i]);
- WRITELN;
- {$ENDIF}
-
- END;
-
- UNTIL regs.CX = 0;
-
- END;
-
- (*=========================================================================*)
- (* Send a string *)
- (*=========================================================================*)
-
- PROCEDURE send_telephone_modem_string;
-
- BEGIN;
-
- active_tcb^.tnc_data.long_length :=
- LENGTH(active_tcb^.tnc_data.str_data);
-
- send_telephone_modem;
-
-
- END;
-
- (*=========================================================================*)
- (* Generate link status change *)
- (*=========================================================================*)
-
- FUNCTION generate_link_status_change : BOOLEAN;
-
- VAR
- b : BOOLEAN;
-
- BEGIN;
-
- (*---------------------------------------------------------------------*)
- (* See if we are connected *)
- (*---------------------------------------------------------------------*)
-
- b := test_phone_connect;
-
- (*---------------------------------------------------------------------*)
- (* Assume we are going to send something *)
- (*---------------------------------------------------------------------*)
-
- generate_link_status_change := TRUE;
-
- (*---------------------------------------------------------------------*)
- (* If we are now connected and we weren't before then connect *)
- (*---------------------------------------------------------------------*)
-
- IF b AND NOT active_port^.port_modem_dcd THEN
- BEGIN;
-
- active_tcb^.tnc_data.str_data := modem_conn;
- active_tcb^.tnc_data.long_length :=
- LENGTH(active_tcb^.tnc_data.str_data);
-
- active_tcb^.tnc_type := t_to_h_links;
- active_tcb^.tnc_null := FALSE;
-
- active_port^.port_modem_dcd := TRUE;
-
- IF active_port^.modem_dial THEN
- active_port^.modem_conn := TRUE;
-
- EXIT;
-
- END;
-
- (*---------------------------------------------------------------------*)
- (* If we are now not connected and we were before then disconnect *)
- (*---------------------------------------------------------------------*)
-
- IF (NOT b) AND active_port^.port_modem_dcd THEN
- BEGIN;
-
- active_tcb^.tnc_data.str_data := t_to_h_disc + 'MODEM';
- active_tcb^.tnc_data.long_length :=
- LENGTH(active_tcb^.tnc_data.str_data);
-
- active_tcb^.tnc_type := t_to_h_links;
- active_tcb^.tnc_null := FALSE;
-
- active_port^.port_modem_dcd := FALSE;
-
- EXIT;
-
- END;
-
- (*---------------------------------------------------------------------*)
- (* Status is quo *)
- (*---------------------------------------------------------------------*)
-
- generate_link_status_change := FALSE;
-
- END;
-
- (*=========================================================================*)
- (* Main line *)
- (*=========================================================================*)
-
- BEGIN;
-
- {$IFDEF DEBUG}
- WRITELN('SMODEM=', tnc_cmd_data, '=', active_tcb^.tnc_data.str_data);
- DELAY(700);
- {$ENDIF}
-
- (*-----------------------------------------------------------------------*)
- (* Initialize *)
- (*-----------------------------------------------------------------------*)
-
- set_dx := active_port^.com_number - 1;
-
- (*-----------------------------------------------------------------------*)
- (* Hit the old modem! *)
- (*-----------------------------------------------------------------------*)
-
- receive_telephone_modem;
-
- (*-----------------------------------------------------------------------*)
- (* Execute *)
- (*-----------------------------------------------------------------------*)
-
- CASE tnc_cmd_data OF
-
- (*---------------------------------------------------------------------*)
- (* Outgoing data *)
- (*---------------------------------------------------------------------*)
-
- 0 : BEGIN;
-
- (*---------------------------------------------------------------*)
- (* Send the data *)
- (*---------------------------------------------------------------*)
-
- {$IFDEF DEBUG}
- WRITELN('STM');
- {$ENDIF}
-
- send_telephone_modem;
-
- (*---------------------------------------------------------------*)
- (* Get anything waiting and empty the buffer *)
- (*---------------------------------------------------------------*)
-
-
- {$IFDEF DEBUG}
- WRITELN('RTM');
- {$ENDIF}
-
- receive_telephone_modem;
-
- (*---------------------------------------------------------------*)
- (* Fake a null response *)
- (*---------------------------------------------------------------*)
-
- set_null;
-
- END;
-
- (*---------------------------------------------------------------------*)
- (* Outgoing command *)
- (*---------------------------------------------------------------------*)
-
- 1 : BEGIN;
-
- s := UPCASE(active_tcb^.tnc_data.str_data[1]);
-
- CASE s OF
-
- (*-------------------------------------------------------------*)
- (* Link state *)
- (*-------------------------------------------------------------*)
-
- 'L':
- BEGIN;
-
- active_tcb^.tnc_data.str_data := '0 0 0 0 0 0';
- active_tcb^.tnc_data.long_length :=
- LENGTH(active_tcb^.tnc_data.str_data);
-
- active_tcb^.tnc_null := FALSE;
- active_tcb^.tnc_type := t_to_h_okmsg;
-
- (*---------------------------------------------------------*)
- (* Set receive buffer waiting *)
- (*---------------------------------------------------------*)
-
- IF (active_tcb^.tnc_in_chn <> NIL)
- OR (active_tcb^.tnc_tth^.data67_count > 0) THEN
- active_tcb^.tnc_data.str_data[3] := '1';
-
- (*---------------------------------------------------------*)
- (* Link status message waiting *)
- (*---------------------------------------------------------*)
-
- b := test_phone_connect;
-
- IF b XOR active_port^.port_modem_dcd THEN
- active_tcb^.tnc_data.str_data[1] := '1';
-
- (*---------------------------------------------------------*)
- (* Link status *)
- (*---------------------------------------------------------*)
-
- IF b THEN
- active_tcb^.tnc_data.str_data[11] := '1';
-
- EXIT;
-
- END;
-
- (*-------------------------------------------------------------*)
- (* Disconnect *)
- (*-------------------------------------------------------------*)
-
- 'D' :
- BEGIN;
-
- set_port_speed(active_port^.data_rate);
-
- (*---------------------------------------------------------*)
- (* Loop thru two times *)
- (*---------------------------------------------------------*)
-
- FOR i := 1 TO 2 DO
- BEGIN;
-
- (*-----------------------------------------------------*)
- (* Set port speed *)
- (*-----------------------------------------------------*)
-
- (* set_port_speed(active_port^.data_rate);*)
-
- (*-----------------------------------------------------*)
- (* Drop DTR and RTS *)
- (*-----------------------------------------------------*)
-
- regs.AX := $0500;
- regs.DX := set_dx;
-
- signal_place^ := $0200 + LO(signal_place^);
-
- INTR(tnc_interrupt, regs);
-
- signal_place^ := $F800 + LO(signal_place^);
-
- (*-----------------------------------------------------*)
- (* Delay *)
- (*-----------------------------------------------------*)
-
- short_wait;
-
- (*-----------------------------------------------------*)
- (* Raise DTR and RTS *)
- (*-----------------------------------------------------*)
-
- regs.AX := $0600;
- regs.DX := set_dx;
-
- signal_place^ := $0200 + LO(signal_place^);
-
- INTR(tnc_interrupt, regs);
-
- signal_place^ := $F800 + LO(signal_place^);
-
- (*-----------------------------------------------------*)
- (* Switch to command mode *)
- (*-----------------------------------------------------*)
-
- short_wait;
-
- active_tcb^.tnc_data.str_data := '+++';
- send_telephone_modem_string;
-
- short_wait;
-
- (*-----------------------------------------------------*)
- (* Hangup *)
- (*-----------------------------------------------------*)
-
- active_tcb^.tnc_data.str_data := 'ATH0' + cr;
- send_telephone_modem_string;
-
-
- END;
-
- (*---------------------------------------------------------*)
- (* Now we send a DED mode error. This tells everyone *)
- (* that the disconnect was successful immediately *)
- (* Yes.. this sounds weird but it's simulating a disconnect*)
- (* send to a channel that is not connected. If we sent *)
- (* an OK, then we would have to have a link status message *)
- (* later to say the DISC was successfull. *)
- (*---------------------------------------------------------*)
-
- IF NOT active_port^.port_modem_dcd THEN
- BEGIN;
- active_tcb^.tnc_data.str_data := 'LINE DISCONNECTED';
- active_tcb^.tnc_data.long_length :=
- LENGTH(active_tcb^.tnc_data.str_data);
-
- active_tcb^.tnc_null := FALSE;
- active_tcb^.tnc_type := t_to_h_badmsg;
- END
- ELSE
- set_null;
-
- EXIT;
-
- END;
-
- (*-------------------------------------------------------------*)
- (* Connect *)
- (*-------------------------------------------------------------*)
-
- 'C' :
- BEGIN;
-
- (*---------------------------------------------------------*)
- (* Change the "C" to "ATD" and add CR *)
- (*---------------------------------------------------------*)
-
- active_tcb^.tnc_data.str_data := 'ATD' +
- COPY(active_tcb^.tnc_data.str_data, 2, 255) + cr;
-
- (*---------------------------------------------------------*)
- (* We removed 1 character and added 4 for a net *)
- (* increase of three in the length *)
- (*---------------------------------------------------------*)
-
- INC(active_tcb^.tnc_data.long_length, 3);
-
- (*---------------------------------------------------------*)
- (* Send data *)
- (*---------------------------------------------------------*)
-
- send_telephone_modem;
-
- (*---------------------------------------------------------*)
- (* Null response *)
- (*---------------------------------------------------------*)
-
- set_null;
-
- END;
-
- (*-------------------------------------------------------------*)
- (* Invalid command *)
- (*-------------------------------------------------------------*)
-
- ELSE
- BEGIN;
-
- WRITELN('Bad command -- ', active_tcb^.tnc_data.str_data);
- DELAY(800);
-
- active_tcb^.tnc_data.str_data := 'INVALID COMMAND -- '
- + active_tcb^.tnc_data.str_data;
- active_tcb^.tnc_data.long_length :=
- LENGTH(active_tcb^.tnc_data.str_data);
-
- active_tcb^.tnc_null := FALSE;
- active_tcb^.tnc_type := t_to_h_badmsg;
-
- EXIT;
- END;
-
- END; (*----- End command case statement -------------------------*)
-
- END; (*----- End outgoing command ---------------------------------*)
-
- (*---------------------------------------------------------------------*)
- (* Poll *)
- (*---------------------------------------------------------------------*)
-
- 2..4:
-
- BEGIN;
-
- (*---------------------------------------------------------------*)
- (* If link status is ok then see if we generate one *)
- (*---------------------------------------------------------------*)
-
- IF (tnc_cmd_data <> 3) AND generate_link_status_change THEN
- EXIT;
-
- (*---------------------------------------------------------------*)
- (* Receive any pending data *)
- (*---------------------------------------------------------------*)
-
- receive_telephone_modem;
-
- (*---------------------------------------------------------------*)
- (* If we are going to pull data out then queue data *)
- (*---------------------------------------------------------------*)
-
- IF tnc_cmd_data < 4 THEN
- queue_received_data;
-
- (*---------------------------------------------------------------*)
- (* Anything in the chain? *)
- (*---------------------------------------------------------------*)
-
- IF active_tcb^.tnc_in_chn <> NIL THEN
- b := tnc_data_queued
- ELSE
- b := FALSE;
-
- (*---------------------------------------------------------------*)
- (* Set null switch *)
- (*---------------------------------------------------------------*)
-
- IF NOT b THEN
- set_null
- ELSE
- active_tcb^.tnc_null := FALSE;
-
- END;
-
- (*---------------------------------------------------------------------*)
- (* Ignore anything else *)
- (*---------------------------------------------------------------------*)
-
- ELSE
- BEGIN;
- WRITELN('TNC CODE - ', tnc_cmd_data);
- END;
-
- END; (*----- End case statement on transaction code ---------------------*)
-
- END; (*----- End main send/receive Modem ----------------------------------*)